package com.jfs.observer;

import com.jfs.enums.SipMethodEnum;
import com.jfs.observer.request.SIPRequestProcessor;
import com.jfs.observer.response.SIPResponseProcessor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.sip.*;
import javax.sip.header.CSeqHeader;
import javax.sip.message.Response;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description 处理sip通信消息
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022-08-23
 */
@Component
@Slf4j
public class SIPProcessorObserver implements SipListener {
    /**
     * 请求处理者集合
     */
    private static final Map<SipMethodEnum, SIPRequestProcessor> REQUEST_PROCESSOR_MAP = new ConcurrentHashMap<>();
    /**
     * 响应处理者集合
     */
    private static final Map<SipMethodEnum, SIPResponseProcessor> RESPONSE_PROCESSOR_MAP = new ConcurrentHashMap<>();

    /**
     * @param requestEvent -
     *                     requestEvent fired from the SipProvider to the SipListener
     *                     representing a Request received from the network.
     */
    @Override
    public void processRequest(RequestEvent requestEvent) {
        //获取请求消息 方法类型
        String method = requestEvent.getRequest().getMethod();
        if (log.isDebugEnabled()) {
            log.debug("收到请求：{}", requestEvent.getRequest());
        }
        SIPRequestProcessor sipRequestProcessor = REQUEST_PROCESSOR_MAP.get(SipMethodEnum.getMethodEnumByName(method));
        if (Objects.isNull(sipRequestProcessor)) {
            log.error("【{}】请求方法没有找到对应的处理器，暂不支持处理", method);
        } else {
            try {
                sipRequestProcessor.doProcess(requestEvent);
            } catch (Exception e) {
                log.error("收到请求发生异常:{}", e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * @param responseEvent -
     *                      the responseEvent fired from the SipProvider to the
     *                      SipListener representing a Response received from the network.
     */
    @Override
    public void processResponse(ResponseEvent responseEvent) {
        try {
            if (log.isDebugEnabled()){
                log.debug("收到响应：{}", responseEvent.getResponse());
            }
            int status = responseEvent.getResponse().getStatusCode();
            if (((status >= 200) && (status < 300)) || status == Response.UNAUTHORIZED) {
                CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
                String method = cseqHeader.getMethod();
                SIPResponseProcessor sipResponseProcessor = RESPONSE_PROCESSOR_MAP.get(SipMethodEnum.getMethodEnumByName(method));
                if (Objects.isNull(sipResponseProcessor)) {
                    log.error("【{}】响应方法没有找到对应的处理器，暂不支持处理", method);
                } else {
                    sipResponseProcessor.doProcess(responseEvent);
                }
            }
        } catch (Exception e) {
            log.error("收到响应发生异常:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * @param timeoutEvent -
     *                     the timeoutEvent received indicating either the message
     *                     retransmit or transaction timed out.
     */
    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
        log.info("----------->processTimeout:{}", timeoutEvent);
    }

    @Override
    public void processIOException(IOExceptionEvent exceptionEvent) {
        log.info("----------->processIOException:{}", exceptionEvent);
    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
        log.info("----------->processTransactionTerminated:{}", transactionTerminatedEvent);
    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
        log.info("----------->processDialogTerminated:{}", dialogTerminatedEvent);
    }

    /**
     * 添加请求处理者
     *
     * @param sipMethodEnum
     * @param sipRequestProcessor
     */
    public void addRequestProcess(SipMethodEnum sipMethodEnum, SIPRequestProcessor sipRequestProcessor) {
        REQUEST_PROCESSOR_MAP.put(sipMethodEnum, sipRequestProcessor);
    }

    /**
     * 添加响应处理者
     *
     * @param sipMethodEnum
     * @param sipRequestProcessor
     */
    public void addResponseProcess(SipMethodEnum sipMethodEnum, SIPResponseProcessor sipRequestProcessor) {
        RESPONSE_PROCESSOR_MAP.put(sipMethodEnum, sipRequestProcessor);
    }
}
